﻿namespace Basic
{
    /// <summary>
    /// 字节数组缓存
    /// </summary>
    public sealed class BytesCacher
    {
        public sealed class Bytes
        {
            private bool inUsing = false;

            /// <summary>
            /// 可用长度，小于等于Buffer的物理长度
            /// </summary>
            public int Length
            {
                get;
                private set;
            }

            public byte[] Buffer
            {
                get;
                private set;
            }

            public Bytes(byte[] buffer)
            {
                Buffer = buffer;
                Length = buffer.Length;
            }

            /// <summary>
            /// 此方法，只能由BytesCacher调用
            /// </summary>
            /// <param name="length"></param>
            public void ResetForUse(int length)
            {
                Length = length;
                inUsing = true;
            }

            /// <summary>
            /// 使用者使用完毕
            /// </summary>
            public void OnUseEnd()
            {
                if (inUsing)
                {
                    inUsing = false;
                    BytesCacher.OnUseEnd(this);
                }
                else
                {
                    throw new System.Exception("Bytes.OnUseEnd called multi times");
                }
            }
        }

        private static int[] cachedSize = new int[] { 256, 512, 1024, 4096, 10240 };
        private static int[] cachedCount = new int[] { 16, 8, 4, 2, 1 };
        private static Cacher<Bytes>[] cached = new Cacher<Bytes>[] { null, null, null, null, null };

        static BytesCacher()
        {
            if (cached.Length != cachedSize.Length || cachedCount.Length != cachedSize.Length)
            {
                throw new System.Exception("cached.Length != cachedSize.Length || cachedCount.Length != cachedSize.Length");
            }

            for (int index = 0; index < cachedSize.Length; ++index)
            {
                cached[index] = new Cacher<Bytes>(cachedCount[index], cachedCount[index], cachedCount[index], () =>
                {
                    return new Bytes(new byte[cachedSize[index]]);
                });
            }
        }

        /// <summary>
        /// 申请最小指定长度的字节数组
        /// </summary>
        /// <param name="minLength"></param>
        /// <returns></returns>
        public static Bytes Alloc(int minLength)
        {
            for (int index = 0; index < cachedSize.Length; ++index)
            {
                if (minLength <= cachedSize[index])
                {
                    var b = cached[index].Alloc();
                    b.ResetForUse(minLength);
                    return b;
                }
            }

            {
                var b = new Bytes(new byte[minLength]);
                b.ResetForUse(minLength);
                return b;
            }
        }

        /// <summary>
        /// 字节数组使用完毕
        /// 由Bytes.OnUseEnd调用
        /// </summary>
        /// <param name="b"></param>
        private static void OnUseEnd(Bytes b)
        {
            for (int index = 0; index < cachedSize.Length; ++index)
            {
                if (b.Length <= cachedSize[index])
                {
                    cached[index].OnUseEnd(b);
                    return;
                }
            }
        }

        /// <summary>
        /// ToString
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            var sb = TempStringBuilderCache.Acquire();

            for (int index = 0; index < cached.Length; ++index)
            {
                sb.AppendLine(cached[index].ToString());
            }
            sb.Remove(sb.Length - 1, 1);

            return TempStringBuilderCache.GetStringAndRelease(sb);
        }
    }
}
